﻿using System.Diagnostics;

namespace DimensionsHelper.LanguageService.Syntax;

public class PreBinaryExpression : PreExpression
{
    private PreExpression _leftOperand;


    private SourceNode _operatorToken;
    private PreExpression _rightOperand;

    internal PreBinaryExpression(SourceNode? parent, SourceNode operatorToken) :
        base(parent, SyntaxKinds.BinaryExpression)
    {
        SetChildField(ref _operatorToken, operatorToken);
        _leftOperand = PreEmptyExpression.DefaultEmptyExpression;
        _rightOperand = PreEmptyExpression.DefaultEmptyExpression;
    }


    public SourceNode OperatorToken => _operatorToken;


    public PreExpression LeftOperand => _leftOperand;


    public PreExpression RightOperand => _rightOperand;


    public PreBinaryExpression Update(SourceNode operatorToken)
    {
        Debug.Assert(SyntaxFacts.IsBinaryOperatorUnchecked(operatorToken.Kind));
        SetChildField(ref _operatorToken, IsNullOrDefault, operatorToken);
        return this;
    }


    public PreBinaryExpression Update(PreExpression rightOperand)
    {
        SetChildField(ref _rightOperand, PreEmptyExpression.IsNullOrDefaultEmptyExpression, rightOperand);
        return this;
    }


    public PreBinaryExpression Update(PreExpression leftOperand, SourceNode? operatorToken,
        PreExpression rightOperand)
    {
        SetChildField(ref _leftOperand, PreEmptyExpression.IsNullOrDefaultEmptyExpression, leftOperand);
        SetChildField(ref _rightOperand, PreEmptyExpression.IsNullOrDefaultEmptyExpression, rightOperand);

        if (operatorToken != null)
        {
            SetChildField(ref _operatorToken, IsNullOrDefault, operatorToken);
        }

        return this;
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        Accept(visitor, LeftOperand, OperatorToken, RightOperand);
    }
}


public static partial class NodeFactory
{
    public static PreBinaryExpression CreatePreBinaryExpression(SourceNode? parent, PreExpression leftOperand,
        SourceNode operatorToken)
    {
        Debug.Assert(SyntaxFacts.IsBinaryOperatorUnchecked(operatorToken.Kind));
        PreBinaryExpression expr = new(parent, operatorToken);
        return expr.Update(leftOperand).Update(operatorToken);
    }


    public static PreBinaryExpression CreatePreBinaryExpression(SourceNode? parent, PreExpression leftOperand,
        SourceNode operatorToken, PreExpression rightOperand)
    {
        Debug.Assert(SyntaxFacts.IsBinaryOperatorUnchecked(operatorToken.Kind));
        PreBinaryExpression expr = new(parent, operatorToken);
        return expr.Update(leftOperand, operatorToken, rightOperand);
    }
}